<?php
// chat_security.php - 聊天系统安全增强模块

/**
 * 过滤用户输入，防止XSS攻击
 * @param string $input 用户输入
 * @return string 过滤后的安全内容
 */
function sanitizeInput($input) {
    // 移除不可见字符
    $input = preg_replace('/\x00-\x1F\x7F/', '', $input);
    
    // 移除HTML标签但保留安全的格式标签
    $allowedTags = '<b><i><u><strong><em><code><pre><br><p><span><div><ul><ol><li>';
    $input = strip_tags($input, $allowedTags);
    
    // 转义特殊字符
    $input = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    
    // 移除JavaScript事件属性
    $input = preg_replace('/(on[a-z]+)\s*=\s*["\'].*?["\']/i', '', $input);
    
    return $input;
}

/**
 * 验证消息内容
 * @param string $message 消息内容
 * @return array [是否有效, 错误信息]
 */
function validateMessage($message) {
    // 检查长度
    $messageLength = mb_strlen($message, 'UTF-8');
    if ($messageLength === 0) {
        return [false, "消息不能为空"];
    }
    if ($messageLength > 500) {
        return [false, "消息不能超过500个字符"];
    }
    
    // 检查危险内容模式
    $dangerPatterns = [
        // JavaScript代码
        '/<script.*?>.*?<\/script>/is',
        // CSS表达式
        '/expression\(.*?\)/is',
        // 数据URI
        '/data\s*:/i',
        // JavaScript伪协议
        '/javascript\s*:/i',
        // iframe标签
        '/<iframe.*?>/is',
        // 外部链接
        '/<a\s+href\s*=\s*["\']\s*(?!https?:\/\/[a-z0-9.-]+\/).*?["\']/is'
    ];
    
    foreach ($dangerPatterns as $pattern) {
        if (preg_match($pattern, $message)) {
            return [false, "消息包含不安全内容"];
        }
    }
    
    return [true, ""];
}

/**
 * 安全输出消息内容
 * @param string $content 消息内容
 * @return string 安全输出的HTML
 */
function safeOutput($content) {
    // 使用HTMLPurifier进行深度过滤
    require_once 'HTMLPurifier/HTMLPurifier.auto.php';
    
    $config = HTMLPurifier_Config::createDefault();
    $config->set('HTML.Allowed', 'b,i,u,strong,em,code,pre,br,p,span,div,ul,ol,li');
    $config->set('AutoFormat.AutoParagraph', true);
    $config->set('AutoFormat.Linkify', false);
    $config->set('HTML.Nofollow', true);
    $config->set('URI.DisableExternalResources', true);
    $config->set('URI.AllowedSchemes', ['http' => true, 'https' => true]);
    
    $purifier = new HTMLPurifier($config);
    return $purifier->purify($content);
}

/**
 * 防止CSRF攻击
 */
function preventCSRF() {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
            http_response_code(403);
            exit("CSRF验证失败");
        }
    }
}

/**
 * 生成CSRF令牌
 */
function generateCSRFToken() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

/**
 * 验证用户会话
 */
function validateUserSession() {
    session_start();
    if (!isset($_SESSION['username'])) {
        header('HTTP/1.1 401 Unauthorized');
        exit("请先登录");
    }
}

/**
 * 限制请求频率
 */
function rateLimitRequests() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $key = 'rate_limit_' . $ip;
    $currentTime = time();
    
    if (!isset($_SESSION[$key])) {
        $_SESSION[$key] = [
            'count' => 0,
            'start_time' => $currentTime
        ];
    }
    
    $rateData = $_SESSION[$key];
    
    // 重置每分钟
    if ($currentTime - $rateData['start_time'] > 60) {
        $rateData = [
            'count' => 0,
            'start_time' => $currentTime
        ];
    }
    
    // 检查是否超过限制
    if ($rateData['count'] >= 30) { // 每分钟最多30条消息
        http_response_code(429);
        exit("发送消息过于频繁，请稍后再试");
    }
    
    // 增加计数
    $rateData['count']++;
    $_SESSION[$key] = $rateData;
}